import tornado.web

from models import address
from views import BaseHandler, SMSHandler
from configs import errorCode, errorMsg, config, const
from utils import util


class AddressHandler(BaseHandler):
    @BaseHandler.auth
    async def post(self):
        """
        ---
        tags:
          - Address
        summary: 创建用户地址
        description:
        parameters:
          - name: user_token
            in: header
            description: user_token
            required: true
            schema:
              type: string

        requestBody:
          description: Post object that needs to be added to the blog
          content:
            application/json:
                schema:
                  type: object
                  properties:
                    receiver:
                        type: string
                        description: 收货人
                    mobile:
                        type: string
                        description: 收货人手机
                    area:
                        type: string
                        description: 地址 省市区
                    address_detail:
                        type: string
                        description: 地址  拼接详细地址
                    is_default:
                        type: boolean
                        example: false
                        description: 是否设为默认地址

        responses:
          '200':
            description: successful operation
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/OkModel'
          '400':
            description: error operation
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/ErrorModel'
        """
        uid = self.current_user
        _, receiver, mobile, area, address_detail, is_default = self.get_address_from_body()
        if not all((receiver, mobile, area, address_detail)):
            return self.write_error(errorCode.INVALID_ARGS, errorMsg.INVALID_ARGS_MSG, status_code=200)
        row_count, res = await address.get_id_is_default_by_uid(uid)

        if row_count > const.MAX_ADDRESSES:
            return self.write_error(errorCode.ADDRESS_LIMIT_ERR, errorMsg.ADDRESS_LIMIT_ERR_MSG, status_code=200)

        is_default_count = 0
        for addr in res:
            is_default_count += addr.get('is_default')

        if is_default_count == 0:
            rows_effect = await address.insert_address_by(uid, receiver, mobile, area, address_detail, 1)
        elif is_default == 1:
            await address.update_addresses_set_not_default(uid)
            rows_effect = await address.insert_address_by(uid, receiver, mobile, area, address_detail, 1)
        else:
            rows_effect = await address.insert_address_by(uid, receiver, mobile, area, address_detail, 0)

        if rows_effect == 0:
            return self.write_error(errorCode.DB_ERR, errorMsg.DB_ERR_MSG, status_code=200)

        return self.write_json()

    @BaseHandler.auth
    async def get(self):
        """
        ---
        tags:
          - Address
        summary: 展示地址
        description: 展示user地址
        parameters:
          - name: user_token
            in: header
            description: user_token
            required: true
            schema:
              type: string

        responses:
          '200':
            description: successful operation
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/AddressModel'
          '400':
            description: error operation
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/ErrorModel'
        """
        uid = self.current_user
        row_count, res = await address.get_addresses_by_uid(uid)
        if row_count == 0:
            return self.write_error(errorCode.ADDRESS_IS_EMPTY, errorMsg.ADDRESS_IS_EMPTY_MSG, status_code=200)
        return self.write_json(res)

    @BaseHandler.auth
    async def delete(self):
        """
        ---
        tags:
          - Address
        summary: 删除地址
        description: 删除地址id对应手机号
        parameters:
          - name: user_token
            in: header
            description: user_token
            required: true
            schema:
              type: string
          - name: id
            in: query
            description: 地址id
            required: true
            schema:
              type: integer


        responses:
          '200':
            description: successful operation
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/OkModel'
          '400':
            description: error operation
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/ErrorModel'
        """
        address_id = self.get_query_argument('id', None)
        if address_id is None:
            return self.write_error(errorCode.INVALID_ARGS, errorMsg.INVALID_ARGS_MSG, status_code=200)

        row_count = await address.delete_address_by_id(address_id)
        if row_count == 0:
            return self.write_error(errorCode.ADDRESS_NOT_EXIST, errorMsg.ADDRESS_NOT_EXIST_MSG, status_code=200)
        return self.write_json()

    @BaseHandler.auth
    async def put(self):
        """
        ---
        tags:
          - Address
        summary: 修改用户地址
        description:
        parameters:
          - name: user_token
            in: header
            description: user_token
            required: true
            schema:
              type: string

        requestBody:
          description: Post object that needs to be added to the blog
          content:
            application/json:
                schema:
                  type: object
                  properties:
                    id:
                        type: string
                        description: 地址id
                    receiver:
                        type: string
                        description: 收货人
                    mobile:
                        type: string
                        description: 收货人手机
                    area:
                        type: string
                        description: 省市区
                    address_detail:
                        type: string
                        description: 详细地址
                    is_default:
                        type: boolean
                        example: false
                        description: 是否设为默认地址

        responses:
          '200':
            description: successful operation
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/OkModel'
          '400':
            description: error operation
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/ErrorModel'
        """
        address_id, receiver, mobile, area, address_detail, is_default = self.get_address_from_body()
        if not all((address_id, receiver, mobile, area, address_detail)):
            return self.write_error(errorCode.INVALID_ARGS, errorMsg.INVALID_ARGS_MSG, status_code=200)

        row_count = await address.update_address_by_id(address_id, receiver, mobile, area, address_detail, is_default)
        if row_count == 0:
            return self.write_error(errorCode.DB_ERR, errorMsg.DB_ERR_MSG, status_code=200)
        return self.write_json()

    def get_address_from_body(self):
        tmp = util.json_decode(self.request.body)
        address_id = tmp.get('id', None)
        receiver = tmp.get('receiver', None)
        mobile = tmp.get('mobile', None)
        area = tmp.get('area', None)
        address_detail = tmp.get('address_detail', None)
        is_default = tmp.get('is_default', None)
        is_default = 0 if not is_default else 1
        return address_id, receiver, mobile, area, address_detail, is_default


class DefaultAddressHandler(BaseHandler):
    @BaseHandler.auth
    async def put(self):
        """
        ---
        tags:
          - Address
        summary: 设置默认用户地址
        description:
        parameters:
          - name: user_token
            in: header
            description: user_token
            required: true
            schema:
              type: string
          - name: id
            in: query
            description: 地址id
            required: true
            schema:
              type: string

        responses:
          '200':
            description: successful operation
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/OkModel'
          '400':
            description: error operation
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/ErrorModel'
        """
        address_id = self.get_query_argument("id", None)
        if address_id is None:
            return self.write_error(errorCode.INVALID_ARGS, errorMsg.INVALID_ARGS_MSG, status_code=200)

        try:
            await address.update_addresses_set_not_default(self.current_user)
            await address.update_address_set_default(address_id)
        except Exception as e:
            self.logger.error(e)
            return self.write_error(errorCode.DB_ERR, errorMsg.DB_ERR_MSG, status_code=200)
        return self.write_json()

    @BaseHandler.auth
    async def get(self):
        """
                ---
                tags:
                  - Address
                summary: 获取默认地址
                description: 获取默认地址，无默认地址则返回一个非默认地址，没有地址则error
                parameters:
                  - name: user_token
                    in: header
                    description: user_token
                    required: true
                    schema:
                      type: string


                responses:
                  '200':
                    description: successful operation
                    content:
                      application/json:
                        schema:
                          $ref: '#/components/schemas/AddressModel'
                  '400':
                    description: error operation
                    content:
                      application/json:
                        schema:
                          $ref: '#/components/schemas/ErrorModel'
                """
        row_count, res = await address.get_address_by_uid(self.current_user)
        if row_count == 0:
            return self.write_error(errorCode.ADDRESS_IS_EMPTY, errorMsg.ADDRESS_IS_EMPTY_MSG, status_code=200)
        return self.write_json(data=res)
